/*
 *
 * Copyright (C) 2012 Walter Lütgenau
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package offset.nodes.server.error.model;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Walter Lütgenau
 */
public class LoggedException extends RuntimeException {

    ExceptionId exceptionId;
    Object[] parameters = null;
    Throwable wrappedException = null;
    static Logger logger = LoggerFactory.getLogger(LoggedException.class);
    static final String bundleName = "/offset/nodes/web/view/LoggedException";

    public LoggedException(ExceptionId id, Object[] parameters, Throwable wrappedException) {
        this.exceptionId = id;
        this.parameters = parameters;
        this.wrappedException = wrappedException;
        log();
    }

    public LoggedException(ExceptionId id, Object[] parameters) {
        this.exceptionId = id;
        this.parameters = parameters;
        log();
    }

    public LoggedException(ExceptionId id, Throwable wrappedException) {
        this.exceptionId = id;
        this.wrappedException = wrappedException;
        log();
    }

    public LoggedException(ExceptionId exceptionId) {
        this.exceptionId = exceptionId;
        log();
    }

    public ExceptionId getExceptionId() {
        return exceptionId;
    }

    public Object[] getParameters() {
        return parameters;
    }

    public Throwable getWrappedException() {
        return wrappedException;
    }
    
    public String getMessage(Locale locale) {
        ResourceBundle bundle = exceptionId.getBundle(locale);
        String key = bundle.getString(getExceptionId().getId());     
        if ( getParameters() == null)
            return key;
        
        return MessageFormat.format(key, getParameters());
    }

    protected String createStackTrace() {
        Writer writer = new StringWriter();
        PrintWriter printer = new PrintWriter(writer);
        try {
            throw new Exception();
        } catch (Exception e) {
            e.printStackTrace(printer);
        }

        return writer.toString();
    }
    
    protected void log() {
        String message = getExceptionId().getId() + ": " + getMessage(Locale.getDefault());
        boolean includeStackTrace = false;
        
        switch (getExceptionId().getSeverity()) {
            case Error:
                if (getWrappedException() == null)
                    logger.error(message);
                else
                    logger.error(message, getWrappedException());
                includeStackTrace = true;
                break;

            case Warning:
                if (getWrappedException() == null)
                    logger.warn(message);
                else
                    logger.warn(message, getWrappedException());
                includeStackTrace = true;
                break;

            case Info:
                if (getWrappedException() == null)
                    logger.info(message);
                else
                    logger.info(message, getWrappedException());
                break;

            case Debug:
                if (getWrappedException() == null)
                    logger.debug(message);
                else
                    logger.debug(message, getWrappedException());
                break;
        }

        if (includeStackTrace)
            message = message + createStackTrace();
    }

}
